import asyncio
import configparser
import logging
import socket
import threading
import time

import websockets

# 获取日志记录器
logger = logging.getLogger(__name__)

# 读取配置文件
config = configparser.ConfigParser()
config.read('config/config.ini', encoding='utf-8')

# 提供默认值
ws_default_host = "0.0.0.0"
ws_default_port = "8765"
broadcast_default_host = '255.255.255.255'
broadcast_default_port = "8766"


ws_host = config['websocket'].get('HOST', ws_default_host)
ws_port = int(config['websocket'].get('PORT', ws_default_port))
broadcast_host = config['socket'].get('BROADCAST_HOST', broadcast_default_host)
broadcast_port = int(config['socket'].get('BROADCAST_PORT', broadcast_default_port))


class WebSocketServer:
    def __init__(self, host=ws_host, port=ws_port):
        self.host = host
        self.port = port
        self.clients = set()  # 存储所有连接的客户端
        self.clients_lock = threading.Lock()  # 添加锁
        self.loop = None  # 获取当前事件循环
        self.udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)

    async def handle_client(self, websocket):
        # 使用锁保护对 clients 的访问
        # 新的客户端连接
        with self.clients_lock:
            self.clients.add(websocket)
        logger.info(f"新客户端连接: {websocket}")
        logger.info(f"当前连接数: {len(self.clients)}")
        try:
            async for message in websocket:
                logger.info(f"当前客户端： {websocket}")
                logger.info(f"收到消息: {message}")
                # 本地做一个udp广播
                self.udp_broadcast(message)
                # 回显消息给客户端
                # await websocket.send(message)
        except websockets.ConnectionClosed as e:
            logger.error(f"客户端断开连接: {e}")
        finally:
            # 移除断开的客户端
            with self.clients_lock:  # 使用锁保护对 clients 的访问
                if websocket in self.clients:
                    self.clients.remove(websocket)
                    logger.info(f"移除客户端: {websocket}")

    async def send_message(self, message):
        """向所有连接的客户端发送消息"""
        with self.clients_lock:  # 使用锁保护对 clients 的访问
            logger.info(f"当前loop ID: {id(asyncio.get_running_loop())}")
            logger.info(f"发送消息: {message}")
            logger.info(f"当前客户端： {self.clients}")
            if not self.clients:
                logger.warning("没有客户端连接，无法发送消息")
                return
            disconnected_clients = set()
            for client in list(self.clients):
                try:
                    await client.send(message)
                except websockets.ConnectionClosed:
                    logger.error(f"客户端断开连接: {client}")
                    disconnected_clients.add(client)
            # 清理已断开的客户端
            logger.info(f"清理已断开的客户端: {disconnected_clients}")
            self.clients -= disconnected_clients

    async def start(self):
        logger.info(f"启动 WebSocket 服务器: ws://{self.host}:{self.port}")
        logger.info(f"WebSocketServer 事件循环 ID: {id(asyncio.get_running_loop())}")
        async with websockets.serve(self.handle_client, self.host, self.port):
            await asyncio.Future()  # 持续运行直到手动停止

    def udp_broadcast(self, message):
        self.udp_socket.sendto(message.encode('utf-8'), (broadcast_host, broadcast_port))
        logger.info(f"UDP广播消息: {message} - {broadcast_host} - {broadcast_port}")


websocket_server = WebSocketServer()


def start_websocket_server():
    global event_loop  # 声明全局事件循环变量
    while True:
        try:
            event_loop = asyncio.new_event_loop()
            logger.info(f"启动... {event_loop}")
            asyncio.set_event_loop(event_loop)
            websocket_server.loop = event_loop  # 设置全局的 websocket_server.loop
            logger.info(f"WebSocketServer 事件循环 ID: {id(event_loop)}")
            task = event_loop.create_task(websocket_server.start())
            event_loop.run_forever()
        except Exception as e:
            logger.error(f"WebSocket服务器异常: {e}")
            logger.info("正在重启WebSocket服务器...")
            task.cancel()
            event_loop.stop()
            asyncio.set_event_loop(None)  # 清除事件循环
            # 确保在重启前等待一段时间，避免频繁重启
            time.sleep(5)
